package com.jt.assistant.ui

import android.annotation.SuppressLint
import android.bluetooth.BluetoothAdapter
import android.content.Intent
import android.os.Bundle
import android.text.InputType
import androidx.recyclerview.widget.LinearLayoutManager
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.input.input
import com.afollestad.materialdialogs.lifecycle.lifecycleOwner
import com.blankj.utilcode.util.GsonUtils
import com.blankj.utilcode.util.ToastUtils
import com.dothantech.lpapi.LPAPI
import com.dothantech.printer.IDzPrinter
import com.gengcon.www.jcprintersdk.JCAPI
import com.gengcon.www.jcprintersdk.callback.Callback
import com.gengcon.www.jcprintersdk.callback.PrintCallback
import com.jt.assistant.R
import com.jt.assistant.adapter.RunturnSkuUploadAdapter
import com.jt.assistant.base.GlobalConfig.JSON_RESULT_SKU_ERROR
import com.jt.assistant.base.GlobalConfig.SCAN_TYPE_ONESHOT
import com.jt.assistant.bean.*
import com.jt.assistant.utils.B11PrinterHelper
import com.jt.assistant.utils.B21PrinterHelper
import com.jt.assistant.utils.FastClickUtil
import com.jt.assistant.viewmodel.HomeViewModel
import com.tencent.mmkv.MMKV
import com.yzp.mvvmlibrary.base.BaseActivity
import kotlinx.android.synthetic.main.activity_seal_goods.*
import kotlinx.android.synthetic.main.activity_seal_goods.rv_returnSku
import kotlinx.android.synthetic.main.activity_seal_goods.top_bar
import kotlinx.android.synthetic.main.activity_seal_home.bt_commit
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.util.*
import kotlin.collections.ArrayList

/**
 * 退货封箱
 */
class SealGoodsActivity : BaseActivity<HomeViewModel>() {
    private val mAdapter by lazy {
        RunturnSkuUploadAdapter(
            ArrayList<CartonGoodsList>()
        )
    }
    private var mCartonResponse: CartonResponseBean? = null
    private var mReturnSku: ReturnSkuBean? = null
    private var mCartonTag = ""

    private var mCurrentPrinter = ""
    private var mCurrentPrinterBean: BtStatus? = null
    private val mBtAdapter: BluetoothAdapter by lazy {
        BluetoothAdapter.getDefaultAdapter()
    }
    private var mB11PrintApi: LPAPI? = null

    private var mB21Printer: JCAPI? = null
    private var isShowToast: Boolean = true
    override fun onDestroy() {
        set_returnSku.unregisterEventBus()
        isShowToast = false
        closePrinter()
        super.onDestroy()
    }

    override fun onResume() {
        super.onResume()
        isShowToast = true

        mCurrentPrinter = MMKV.defaultMMKV().getString("CURRENT_PRINTER", "").toString()


        if (!mBtAdapter.isEnabled) {
            //蓝牙未打开
            showTipDialog("当前未连接打印机,请点击确定设置蓝牙打印机")
            return
        }

        if (mCurrentPrinter.isEmpty()) {
            //未连接打印机
            showTipDialog("当前未连接打印机,请点击确定设置蓝牙打印机")
            return
        } else {
            mCurrentPrinterBean = GsonUtils.fromJson(mCurrentPrinter, BtStatus::class.java)
        }


        if (mCurrentPrinterBean!!.name.contains("B11")) {
            //B11
            mB11PrintApi = LPAPI.Factory.createInstance(mB11Callback)
        } else {
            //B21
            mB21Printer = JCAPI.getInstance(initCallback())
        }

        if (!isPrinterConnected()) {
            GlobalScope.launch {
                delay(500)
                //连接打印机
                connectPrinter()
            }
        }
    }


    override fun layoutId(): Int = R.layout.activity_seal_goods

    override fun initView(savedInstanceState: Bundle?) {
        set_returnSku.initCamera(this, SCAN_TYPE_ONESHOT)
        with(rv_returnSku) {
            layoutManager = LinearLayoutManager(context)
            adapter = mAdapter
        }
    }

    @SuppressLint("SetTextI18n")
    override fun initData() {
        tv_channelNo.text = "退货单号: ${intent.getStringExtra("RETURNS_CODE")}"

        mReturnSku = GsonUtils.fromJson(
            intent.getStringExtra("RETURN_SKU_LIST"),
            ReturnSkuBean::class.java
        )

    }

    override fun initListener() {

        top_bar.mTvRightTitle.setOnClickListener {
            isShowToast = false
            closePrinter()
            startActivity(Intent(this, BluetoothActivity::class.java))
        }

        set_returnSku.setOnScanListener {

            if (it.isNullOrEmpty()) {
                ToastUtils.showShort("请扫入SKU码")
                set_returnSku.clearData()
                return@setOnScanListener
            }

            val sku = getSku(it) //转码
            if (sku.isEmpty()) {
                speakString("无效条码")
                set_returnSku.clearData()
                return@setOnScanListener
            }

            for (position in mAdapter.data.indices) {
                if (mAdapter.data[position].sku == sku) {
                    val newSkuNum = mAdapter.data[position].num.toInt() + 1

                    if (justSkuNum(sku, newSkuNum)) {
                        speakString("扫码成功")
                        mAdapter.data[position].num = newSkuNum.toString()
                        mAdapter.notifyDataSetChanged()
                    } else {
                        speakString("数量异常")
                    }
                    set_returnSku.clearData()
                    return@setOnScanListener
                }
            }
            speakString("扫码成功")
            mAdapter.data.add(CartonGoodsList(sku, "1"))
            mAdapter.notifyDataSetChanged()
            set_returnSku.clearData()
        }

        mAdapter.setOnItemClickListener { adapter, view, position ->
            showNumEditDialog(mAdapter.data[position].sku, position)
        }

        mAdapter.setOnItemLongClickListener { adapter, view, position ->
            showDeleteDialog("是否删除 ${mAdapter.data[position].sku} ?", position)
            true
        }


        tv_channelNo.setOnClickListener {
            startActivity(Intent(this@SealGoodsActivity, ReturnsSkuActivity::class.java).apply {
                putExtra("RETURNS_CODE", intent.getStringExtra("RETURNS_CODE"))
            })
        }

        bt_commit.setOnClickListener {
            if (FastClickUtil.isFastClick()) { //avoid fast click
                return@setOnClickListener
            }

            if (mCartonTag.isEmpty()) {
                mCartonTag = UUID.randomUUID().toString()
            }

            if (mAdapter.data.isEmpty()) {
                ToastUtils.showShort("未完成输入")
                return@setOnClickListener
            }
            //判断是否连接上打印机
            if (!isPrinterConnected()) {
                ToastUtils.showShort("打印机未连接,请检查打印机是否开启")
                return@setOnClickListener
            }

            if (mCartonResponse != null) {
                printCode(mCartonResponse!!)
                return@setOnClickListener
            }

            val params = Param::class.java.newInstance()
            params.channelOrderNo = intent.getStringExtra("RETURNS_CODE").toString()
            params.cartonTag = mCartonTag
            params.cartonGoodsList = mAdapter.data
            viewModel.sendReturnsPackingList(params)

        }

        viewModel.mSendReturnsPackingList.observe(this, {
            if (it.isSuccess()) {
                mAdapter.setErrorCode("")
                mCartonResponse = it.data
                printCode(mCartonResponse!!)

            } else if (it.errorCode == JSON_RESULT_SKU_ERROR) {
                mAdapter.setErrorCode(it.errorMsg)
                ToastUtils.showShort("${it.errorMsg}  SKU数量异常")
            }
        })

    }


    private fun getSku(code: String): String {
        mReturnSku!!.goodsList.forEach {
            if (it.barcode == code || it.sku == code) {
                return it.sku
            }
        }
        return ""
    }

    private fun showDeleteDialog(title: String, position: Int) {
        MaterialDialog(this).show {
            title(text = title)
            positiveButton(text = "确定删除") {
                mAdapter.data.removeAt(position)
                mAdapter.notifyDataSetChanged()
            }
            negativeButton(text = "取消") {}
            lifecycleOwner(this@SealGoodsActivity)
        }
    }

    private fun showNumEditDialog(sku: String, position: Int) {
        MaterialDialog(this).show {
            title(text = "修改  $sku  数量")
            input(
                hint = "请输入数量",
                inputType = InputType.TYPE_CLASS_NUMBER
            ) { _, text ->
                if (justSkuNum(sku, text.toString().toInt())) {
                    mAdapter.data[position].num = text.toString()
                    mAdapter.notifyDataSetChanged()
                } else {
                    speakString("数量异常")
                }
            }
            positiveButton(text = "确定修改")
            negativeButton(text = "取消")
            lifecycleOwner(this@SealGoodsActivity)
        }
    }

    private fun justSkuNum(sku: String, num: Int): Boolean {
        if (num < 1) return false
        mReturnSku!!.goodsList.forEach {
            if (it.sku == sku) {
                if (it.totalNum < num) {
                    return false
                }
            }
        }
        return true
    }

    /***********************************************打印机****************************/


    private fun printCode(data: CartonResponseBean) {
        if (mCurrentPrinterBean!!.name.contains("B11")) {
            B11PrinterHelper.B11PrintData(mB11PrintApi, data)
        } else {//B21打印机
            B21PrinterHelper.B21PrintData(mB21Printer, data, false)
            mB21Printer!!.commitJob(1, 1, 3, mB21PrintCallback)
        }
    }

    private fun closePrinter() {
        if (mCurrentPrinterBean != null)
            GlobalScope.launch {
                if (mCurrentPrinterBean!!.name.contains("B11")) {
                    if (mB11PrintApi != null) mB11PrintApi!!.quit()
                } else {
                    if (mB21Printer != null) mB21Printer!!.close()
                }
            }
    }

    private fun connectPrinter() {
        if (mCurrentPrinterBean!!.name.contains("B11")) {
            //B11
            mB11PrintApi!!.openPrinterByAddress(
                IDzPrinter.PrinterAddress(
                    mCurrentPrinterBean!!.name,
                    mCurrentPrinterBean!!.address,
                    IDzPrinter.AddressType.SPP
                )
            )

        } else {
            //B21
            initPrintCallback()
            mB21Printer!!.openPrinterByAddress(
                application, mCurrentPrinterBean!!.address, 0
            )
        }
    }


    private fun isPrinterConnected(): Boolean {
        if (mCurrentPrinterBean!!.name.contains("B11")) {
            //B11
            val state = mB11PrintApi!!.printerState
            // 打印机未连接
            if (state == null || state == IDzPrinter.PrinterState.Disconnected || state == IDzPrinter.PrinterState.Connecting) {
                return false
            }
        } else {
            //B21打印机
            if (mB21Printer!!.isConnection != 0) {
                return false
            }
        }
        // 打印机已连接
        return true
    }


    private fun showTipDialog(text: String) {
        MaterialDialog(this).show {
            title(text = text)
            positiveButton(text = "确定") {
                startActivity(Intent(this@SealGoodsActivity, BluetoothActivity::class.java))
            }
            negativeButton(text = "取消") {}
            lifecycleOwner(this@SealGoodsActivity)
        }
    }

    private fun showVolumeInput() {
        MaterialDialog(this).show {
            title(text = "退货单${intent.getStringExtra("RETURNS_CODE").toString()}商品已全部封箱，是否立刻上报体积？")
            positiveButton(text = "确定") {
                startActivity(Intent(this@SealGoodsActivity, WaybillActivity::class.java).apply {
                    putExtra("RETURNS_CODE", intent.getStringExtra("RETURNS_CODE").toString())
                })
            }
            negativeButton(text = "取消") {}
            lifecycleOwner(this@SealGoodsActivity)
        }
    }


    private val mB11Callback: LPAPI.Callback = object : LPAPI.Callback {
        // 打印机连接状态发生变化时被调用
        override fun onStateChange(arg0: IDzPrinter.PrinterAddress, arg1: IDzPrinter.PrinterState) {
            runOnUiThread {
                when (arg1) {
                    IDzPrinter.PrinterState.Connected, IDzPrinter.PrinterState.Connected2 -> {
                        ToastUtils.showShort("打印机连接成功")
                    }
                    IDzPrinter.PrinterState.Disconnected -> {
                        if (isShowToast)
                        speakString("打印机连接失败")
                    }
                    else -> {
                    }
                }
            }

        }

        // 蓝牙适配器状态发生变化时被调用
        override fun onProgressInfo(arg0: IDzPrinter.ProgressInfo, arg1: Any) {}
        override fun onPrinterDiscovery(
            arg0: IDzPrinter.PrinterAddress,
            arg1: IDzPrinter.PrinterInfo
        ) {
        }

        // 打印标签的进度发生变化是被调用
        override fun onPrintProgress(
            address: IDzPrinter.PrinterAddress,
            bitmapData: Any,
            progress: IDzPrinter.PrintProgress,
            addiInfo: Any
        ) {
            runOnUiThread {
                when (progress) {
                    IDzPrinter.PrintProgress.Success -> {
                        mAdapter.data.clear()
                        mAdapter.notifyDataSetChanged()
                        speakString("封箱成功")
                        mCartonTag = ""
                        if (mCartonResponse != null && mCartonResponse!!.isComplete) {
                            showVolumeInput()
                        }
                        mCartonResponse = null
                    }
                    IDzPrinter.PrintProgress.Failed -> {
                        speakString("封箱失败,检查是否缺纸")
                    }
                    else -> {
                    }
                }
            }
        }
    }


    private var mB21PrintCallback: PrintCallback? = null
    private fun initPrintCallback() {
        mB21PrintCallback = object : PrintCallback {
            override fun onPrintProgress(i: Int) {
                //打印精度回调
            }

            override fun onPrintPageCompleted() {
                //页打印完成回调
                runOnUiThread {
                    mB21Printer!!.endJob()
                    mAdapter.data.clear()
                    mAdapter.notifyDataSetChanged()
                    speakString("封箱成功")
                    mCartonTag = ""
                    if (mCartonResponse != null && mCartonResponse!!.isComplete) {
                        showVolumeInput()
                    }
                    mCartonResponse = null
                }
            }

            override fun onRibbonUsed(v: Double) {
                //碳带使用长度上报
            }

            override fun onPageNumberReceivingTimeout() {
                //页码接收超时

            }

            override fun onAbnormalResponse(i: Int) {
                //打印异常回调,部分回调需要调用结束打印
                runOnUiThread {
                    //打印异常回调,部分回调需要调用结束打印
                    if (i > 24) return@runOnUiThread
                    mB21Printer!!.endJob()
                    speakString("打印机异常,请检查打印机")

                }
            }
        }
    }

    private fun initCallback(): Callback? {

        /*
         * 创建全局回调
         */
        return object : Callback {
            override fun onConnectSuccess(s: String, i: Int) {
                //打印机连接成功
                runOnUiThread {
                    ToastUtils.showShort("打印机连接成功")
                }

            }

            override fun onDisConnect() {
                //打印机断开及连接失败回调 （SDK内部无广播。关闭打印机及关闭蓝牙此处不会回调。需要实时监听状态 需要用到蓝牙广播）
                runOnUiThread {
                    if (isShowToast)
                    speakString("打印机连接失败")
                }

            }

            override fun onElectricityChange(i: Int) {
                //打印机电量变化
            }

            override fun onCoverStatus(i: Int) {
                //打印机上盖状态监听

                //打印机上盖状态监听
                if (i == 0) showMainToast("打印机开盖")
            }

            override fun onPaperStatus(i: Int) {

                //打印机标签装入状态监听
                if (i == 1) showMainToast("打印机缺纸")

            }

            override fun onHeartDisConnect() {
                //心跳断开，此处应调用断开打印机
                mB21Printer!!.close()
            }
        }
    }

    private fun showMainToast(string: String) {
        runOnUiThread {
            speakString(string)
            showTip(string)
        }
    }

    private var dialog: MaterialDialog? = null
    private fun showTip(tip: String) {
        if (dialog != null && dialog!!.isShowing) dialog!!.dismiss()
        dialog = MaterialDialog(this).show {
            title(text = tip)
            positiveButton(text = "确定")
            lifecycleOwner(this@SealGoodsActivity)
        }
    }

}